/*  
 *  Copyright 2006 Paul Jack.
 *
 *  This file is part of the Dex compiler suite. 
 *  
 *  Dex is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by the
 *  Free Software Foundation; either version 2 of the License, or (at your
 *  option) any later version.
 *  
 *  Dex is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
 *  Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */
package dex.compiler.model.expression;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;


/**
 * Unary operators.
 */
public enum Unary {

	/** The <code>!</code> operator. */
	NOT("!", Unary.BOOLEAN),
	
	/** The <code>-</code> operator. */
	NEGATE("-", Unary.INTEGER | Unary.FLOAT),
	
	/** The <code>~</code> operator. */
	INVERT("~", Unary.INTEGER);
	
	
	/** Bit that indicates that the operator works on integer types. */
	final private static int INTEGER = 1;
	
	/** Bit that indicates that the operator works on floating-point types. */
	final private static int FLOAT = 2;
	
	/** Bit that indicates that the operator works on boolean types. */
	final private static int BOOLEAN = 4;

	
	/**
	 * The set of operator symbols.  Helps the parser along.
	 * This set is read-only.
	 */
	final public static Set<String> SYMBOLS = makeSymbolSet();

	
	/**
	 * The symbol for the operator.
	 */
	private String symbol;
	
	
	/**
	 * The flags for the operator.
	 */
	private int flags;
	

	/**
	 * Constructs a new unary operator.
	 * 
	 * @param symbol  the symbol for the operator
	 * @param flags  the flags for the operator
	 */
	private Unary(String symbol, int flags) {
		this.symbol = symbol;
		this.flags = flags;
	}


	/**
	 * Returns true if an operator can operate on integer types.
	 * 
	 * @return  true if an operator can operate on integer types
	 */
	public boolean isInteger() {
		return (flags & INTEGER) == INTEGER;
	}

	
	/**
	 * Returns true if an operator can operate on the boolean type.
	 * 
	 * @return  true if an operator can operate on the boolean type
	 */
	public boolean isBoolean() {
		return (flags & BOOLEAN) == BOOLEAN;
	}
	
	
	/**
	 * Returns true if an operator can operate on floating-point types
	 * 
	 * @return  true if an operator can operate on floating-point types
	 */
	public boolean isFloat() {
		return (flags & FLOAT) == FLOAT;
	}

	
	/**
	 * Returns the symbol for the operator.
	 * 
	 * @return  the operator's symbol
	 */
	public String getSymbol() {
		return symbol;
	}


	/**
	 * Makes the set of symbols.
	 *
	 * @return  the set of all unary operator symbols
	 */
	private static Set<String> makeSymbolSet() {
		HashSet<String> result = new HashSet<String>();
		for (Unary op : values()) {
			result.add(op.getSymbol());
		}
		return Collections.unmodifiableSet(result);
	}
	
	
	/**
	 * Returns the operator for a given symbol.
	 * Or, null if the given string is not an operator symbol.
	 * 
	 * @param symbol  the symbol whose operator to return 
	 * @return  that operator, or null if not found
	 */
	public static Unary get(String symbol) {
		for (Unary op : values()) {
			if (op.symbol.equals(symbol)) {
				return op;
			}
		}
		return null;
	}


}
